package com.xingfei.blog.service.impl;

import com.xingfei.blog.baseMapper.UserInfoMapper;
import com.xingfei.blog.baseMapper.UserMapper;
import com.xingfei.blog.constants.ErrorConstants;
import com.xingfei.blog.dto.UserInfoDTO;
import com.xingfei.blog.mapper.UserInfoDOExtMapper;
import com.xingfei.blog.mapper.UserInfoDOMapper;
import com.xingfei.blog.model.UserDO;
import com.xingfei.blog.model.UserInfoDO;
import com.xingfei.blog.model.UserInfoDOExample;
import com.xingfei.blog.result.ResultConstructor;
import com.xingfei.blog.result.ServiceResult;
import com.xingfei.blog.service.BlogUserInfoService;
import com.xingfei.blog.utils.DistributedLock;
import com.xingfei.blog.vo.PageVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @author: chenxingfei
 * @time: 2017/1/19  12:01
 * To change this template use File | Settings | File Templates.
 */
@Service("blogUserInfoService")
public class BlogUserInfoServiceImpl implements BlogUserInfoService {

    @Autowired
    private UserInfoDOExtMapper userInfoDOExtMapper;

    @Autowired
    private UserInfoDOMapper userInfoDOMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private UserMapper userMapper;

    @Value("${dubbo.register.zookeeper.address}")
    private String zookeeper;

    @Override
    public ServiceResult<UserInfoDTO> getUserInfoById(Long id) {
        //校验参数合法性
        if (ObjectUtils.isEmpty(id)) {
            //返回参数错误结果
            return ResultConstructor.buildServiceErrResult(ErrorConstants.RES_SERVICE_STRING, "条件错误");
        }
        UserInfoDO userInfoDO = this.userInfoDOMapper.selectByPrimaryKey(id);
        if (!ObjectUtils.isEmpty(userInfoDO)) {
            //复制对象，转换为dto
            UserInfoDTO userInfoDTO = new UserInfoDTO();
            BeanUtils.copyProperties(userInfoDO, userInfoDTO);
            //返回结果
            return ResultConstructor.buildSuccessResult(userInfoDTO);
        }
        //返回错误结果
        return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "未查询到数据", null);
    }

    @Override
    @Transactional
    public ServiceResult<UserInfoDTO> saveUserInfoByDTO(UserInfoDTO userInfoDTO) {
        //校验条件
        if (ObjectUtils.isEmpty(userInfoDTO)) {
            //返回参数错误结果
            return ResultConstructor.buildServiceErrResult(ErrorConstants.RES_SERVICE_STRING, "条件错误");
        }
        //将dto转换为do
        UserInfoDO userInfoDO = new UserInfoDO();
        userInfoDTO.setRegisterTime(new Date());
        BeanUtils.copyProperties(userInfoDTO, userInfoDO);
        Long userInfoBackId = this.userInfoDOExtMapper.saveUserInfoBackId(userInfoDO);
        if (ObjectUtils.isEmpty(userInfoBackId)) {
            //返回添加错误信息
            return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "数据添加失败", null);
        } else {
            userInfoDTO.setId(userInfoBackId);
            //返回结果
            return ResultConstructor.buildSuccessResult(userInfoDTO);
        }
    }

    @Override
    @Transactional
    public ServiceResult<Boolean> removeUserInfoByUserId(Long userId) {
        UserInfoDOExample example = new UserInfoDOExample();
        example.createCriteria().andUserIdEqualTo(userId);
        int i = this.userInfoDOMapper.deleteByExample(example);
        if (i > 0) {
            //删除成功
            return ResultConstructor.buildSuccessResult(Boolean.TRUE);
        } else {
            //返回错误结果
            return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "未查询到数据", null);
        }
    }

    @Override
    public ServiceResult<Boolean> updateUserInfoByDTO(UserInfoDTO userInfoDTO) {
        //校验参数合法性
        if (userInfoDTO == null || userInfoDTO.getUserId() == null) {
            //返回参数错误结果
            return ResultConstructor.buildServiceErrResult(ErrorConstants.RES_SERVICE_STRING, "条件错误");
        }
        //更新用户信息
        DistributedLock lock = null;
        try {
            zookeeper=zookeeper.substring(zookeeper.lastIndexOf("/")+1,zookeeper.length());
            lock = new DistributedLock(zookeeper,"lock_username");
            //分布式锁执行
            System.out.println("=====>分布式锁执行");
            lock.lock();
            //执行判断用户名是否存在
            ServiceResult<Integer> serviceResult = null;
            if(StringUtils.isNotBlank(userInfoDTO.getUserName())){
                serviceResult = this.checkUserName(userInfoDTO.getUserName());
            }
            //update username
            if (serviceResult != null && serviceResult.getCode() == ErrorConstants.RES_SUCCESS) {
                if(serviceResult.getResult()>0){
                    return ResultConstructor.buildSuccessResult(ErrorConstants.RESULT_USERNAME_REPET, "用户名已存在", false);
                }
            }
                UserInfoDOExample example = new UserInfoDOExample();
                example.createCriteria().andUserIdEqualTo(userInfoDTO.getUserId());
                UserInfoDO userInfoDO = new UserInfoDO();
                BeanUtils.copyProperties(userInfoDTO, userInfoDO);
                if(StringUtils.isNotBlank(userInfoDTO.getUserName())){
                    UserDO userDO = new UserDO();
                    userDO.setId(userInfoDTO.getUserId());
                    userDO.setUserName(userInfoDTO.getUserName());
                    if (this.userInfoDOMapper.updateByExampleSelective(userInfoDO, example) > 0 && this.userMapper.updateByPrimaryKeySelective(userDO)>0) {
                        return ResultConstructor.buildSuccessResult(Boolean.TRUE);
                    } else {
                        //返回错误结果
                        return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "更新失败", false);
                    }
                }else{
                    if (this.userInfoDOMapper.updateByExampleSelective(userInfoDO, example) > 0) {
                        return ResultConstructor.buildSuccessResult(Boolean.TRUE);
                    } else {
                        //返回错误结果
                        return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "更新失败", false);
                    }
                }
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if(lock != null)
                lock.unlock();
            System.out.println("=====>分布式锁释放");
        }
        return null;
    }

    /**
     * GroboUtils-5-core.jar 多线程测试代码
     * @param userInfoDTO
     * @return
     */
    /*public void MultiRequestsTest(UserInfoDTO userInfoDTO) {
        // 构造一个Runner
        TestRunnable runner = new TestRunnable() {
            @Override
            public void runTest() throws Throwable {
                *//*UserInfoDTO userInfoDTO = new UserInfoDTO();
                userInfoDTO.setUserName("十六");
                userInfoDTO.setUserId(89l);*//*
                ServiceResult<Boolean> serviceResult = updateUserInfoByDTO(userInfoDTO);
                System.out.println(serviceResult);
            }
        };
        int runnerCount = 5;
        //Rnner数组，想当于并发多少个。
        TestRunnable[] trs = new TestRunnable[5];
        for (int i = 0; i < runnerCount; i++) {
            trs[i] = runner;
        }
        // 用于执行多线程测试用例的Runner，将前面定义的单个Runner组成的数组传入
        MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs);
        try {
            // 开发并发执行数组里定义的内容
            mttr.runTestRunnables();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }*/
    @Override
    public ServiceResult<Integer> countUserInfoByDTO(UserInfoDTO userInfoDTO) {
        //校验参数合法性
        if (userInfoDTO == null || userInfoDTO.getUserId() == null) {
            //返回参数错误结果
            return ResultConstructor.buildServiceErrResult(ErrorConstants.RES_SERVICE_STRING, "条件错误");
        }
        //根据条件获取个数
        UserInfoDO userInfoDO = new UserInfoDO();
        BeanUtils.copyProperties(userInfoDTO,userInfoDO);
        UserInfoDOExample example = new UserInfoDOExample();
        UserInfoDOExample.Criteria criteria = example.createCriteria();
        //校验条件
        if(userInfoDO.getId()!=null){
            criteria.andIdEqualTo(userInfoDO.getId());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getAddress())){
            criteria.andAddressEqualTo(userInfoDO.getAddress());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getAvatarUrl())){
            criteria.andAvatarUrlEqualTo(userInfoDO.getAvatarUrl());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getBloodType())){
            criteria.andBloodTypeEqualTo(userInfoDO.getBloodType());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getDescription())){
            criteria.andDescriptionEqualTo(userInfoDO.getDescription());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getEmail())){
            criteria.andEmailEqualTo(userInfoDO.getEmail());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getGraduateSchool())){
            criteria.andGraduateSchoolEqualTo(userInfoDO.getGraduateSchool());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getLastLoginIp())){
            criteria.andLastLoginIpEqualTo(userInfoDO.getLastLoginIp());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getPhone())){
            criteria.andPhoneEqualTo(userInfoDO.getPhone());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getQqOppenId())){
            criteria.andQqOppenIdEqualTo(userInfoDO.getQqOppenId());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getRegisterIp())){
            criteria.andRegisterIpEqualTo(userInfoDO.getRegisterIp());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getSays())){
            criteria.andSaysEqualTo(userInfoDO.getSays());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getSex())){
            criteria.andSexEqualTo(userInfoDO.getSex());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getUserName())){
            criteria.andUserNameEqualTo(userInfoDO.getUserName());
        }
        else if(StringUtils.isNotBlank(userInfoDO.getWeiboUid())){
            criteria.andWeiboUidEqualTo(userInfoDO.getWeiboUid());
        }
        else if(userInfoDO.getBirthday()!=null){
            criteria.andBirthdayEqualTo(userInfoDO.getBirthday());
        }
        else if(userInfoDO.getIsFreeze()!=null){
            criteria.andIsFreezeEqualTo(userInfoDO.getIsFreeze());
        }
        else if(userInfoDO.getIsLock()!=null){
            criteria.andIsLockEqualTo(userInfoDO.getIsLock());
        }
        else if(userInfoDO.getLastUpdateBlogTime()!=null){
            criteria.andLastUpdateBlogTimeEqualTo(userInfoDO.getLastUpdateBlogTime());
        }
        int counts = this.userInfoDOMapper.countByExample(example);
        if (counts > 0) {
            //删除成功
            return ResultConstructor.buildSuccessResult(counts);
        } else {
            //返回错误结果
            return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "更新失败", null);
        }
    }

    @Override
    public ServiceResult<List<UserInfoDTO>> listUserInfoByDTO(UserInfoDTO userInfoDTO) {
        //校验参数合法性
        if (userInfoDTO == null) {
            //返回参数错误结果
            return ResultConstructor.buildServiceErrResult(ErrorConstants.RES_SERVICE_STRING, "条件错误");
        }
        //根据条件获取个数
        UserInfoDO userInfoDO = new UserInfoDO();
        BeanUtils.copyProperties(userInfoDTO,userInfoDO);
        List<UserInfoDO> userInfoDOS =  this.userInfoDOExtMapper.listUserInfoByDO(userInfoDO);
        return dealDuplicateData(userInfoDOS);
    }

    private void copyUserInfoObj(List<UserInfoDO> userInfoDOS, ArrayList<UserInfoDTO> userInfoDTOS) {
        for (UserInfoDO infoDO : userInfoDOS  ) {
            UserInfoDTO DTO = new UserInfoDTO();
            BeanUtils.copyProperties(infoDO,DTO);
            userInfoDTOS.add(DTO);
        }
    }

    /**
     * 获取推荐作者列表
     * 目前计算方法（根据用户发布文章数倒叙）
     * @return
     */
    @Override
    public ServiceResult<List<UserInfoDTO>> listRecommendAuthor() {
        List<UserInfoDO> userInfoDOS = this.userInfoMapper.listRecommendAuthor();
        if(!CollectionUtils.isEmpty(userInfoDOS)){
            ArrayList<UserInfoDTO> userInfoDTOS = new ArrayList<>();
            copyUserInfoObj(userInfoDOS, userInfoDTOS);
            return ResultConstructor.buildSuccessResult(userInfoDTOS);
        }
        //返回错误结果
        return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "未查询到数据", null);
    }

    @Override
    public ServiceResult<List<UserInfoDTO>> listUserInfoByDTO(PageVo pageVo, UserInfoDTO userInfoDTO) {
        //校验参数合法性
        if (userInfoDTO == null) {
            //返回参数错误结果
            return ResultConstructor.buildServiceErrResult(ErrorConstants.RES_SERVICE_STRING, "条件错误");
        }
        //根据条件获取个数
        UserInfoDO userInfoDO = new UserInfoDO();
        BeanUtils.copyProperties(userInfoDTO,userInfoDO);
        List<UserInfoDO> userInfoDOS =  this.userInfoDOExtMapper.listUserInfoByDOByPage(pageVo.getStart(),pageVo.getLimit(),userInfoDO);
        return dealDuplicateData(userInfoDOS);
    }

    /**
     * 抽取公共数据返回
     * @param userInfoDOS
     * @return
     */
    private ServiceResult<List<UserInfoDTO>> dealDuplicateData(List<UserInfoDO> userInfoDOS) {
        if(CollectionUtils.isEmpty(userInfoDOS)){
            //返回错误结果
            return ResultConstructor.buildSuccessResult(ErrorConstants.SERVER_SUCCESS, "查询数据失败失败", null);
        }else{
            ArrayList<UserInfoDTO> userInfoDTOS = new ArrayList<>();
            copyUserInfoObj(userInfoDOS, userInfoDTOS);
            //返回成功结果
            return ResultConstructor.buildSuccessResult(userInfoDTOS);
        }
    }

    @Override
    public ServiceResult<Integer> checkUserName(String userName) {
        UserInfoDO udo = new UserInfoDO();
        udo.setUserName(userName);
        int i = userInfoMapper.selectCount(udo);
        return ResultConstructor.buildSuccessResult(i);
    }
}
